/*
 * @Author: actor
 * @Date: 2023-11-13 15:43:57
 * @email: 395593455@qq.com
 * @LastEditors: actor
 * @LastEditTime: 2023-12-19 10:11:49
 * @FilePath: \i-hos-app\shared\emr\src\hooks\useEdit.ts
 * @Description: 富文本操作编辑
 */
import { toRefs } from 'vue'
import { ElMessage } from 'element-plus'
// 接口约束
import { IPageConfigStore } from '../interface/page'
// store数据
import { usePageConfigStore } from '../store/pageConfig'

// 获取选取所有的元素
const getRangeHtml = (): any => {
  // 获取当前的选区
  let selection: any = window.getSelection && window.getSelection()
  if (selection.rangeCount === 0) {
    return
  }

  // 选中区域的html
  let rangeAt: any = selection.getRangeAt(0)
  let commonAncestorContainer: any = rangeAt.commonAncestorContainer
  let childNodes: any = commonAncestorContainer.childNodes

  // 初始获取选中区域开始和结束的value值
  let startContainer: string = rangeAt.startContainer.nodeValue
  let endContainer: string = rangeAt.endContainer.nodeValue

  //用来存放获取到的所有的标签
  let childArr: any = []

  if (!childNodes.length && commonAncestorContainer.parentElement.id != 'emr_page_body') {
    childArr.push(commonAncestorContainer.parentElement)
  } else {
    // 找出选取所有的html元素
    let childfn = (obj: any): void => {
      for (let i: number = 0; i < obj.length; i++) {
        //当当前元素还存在子元素的时候,递归
        if (obj[i].childNodes) {
          childfn(obj[i].childNodes)
        }
        //遍历到的元素添加到childArr这个数组中间, 排除br元素
        if (obj[i].tagName != 'BR') {
          childArr.push(obj[i])
        }
      }
    }
    childfn(childNodes)
  }

  return {
    childArr,
    commonAncestorContainer,
    startContainer,
    endContainer,
  }
}

// 创建一个div元素
const createDiv = (dom: any): void => {
  // 判断当前选中的区域是不是纯文本，是纯文本动态添加一个父元素div
  if (dom.parentElement.id == 'emr_page_body') {
    let insertDiv: any = document.createElement('span')
    // insertDiv.style.display = 'inline-block'
    let parent: any = dom.parentElement
    parent.replaceChild(insertDiv, dom)
    insertDiv.append(dom)
  }
}

// 设置选取元素的样式
const setStyle = (ev: string, value: string): void => {
  let { childArr, commonAncestorContainer, startContainer, endContainer } = getRangeHtml()

  // 初始化选中区域的开始和结束位置
  let startIndex: number = 0
  let endIndex: number = 0

  // 设置选中元素的行距
  if (!childArr.length) {
    // 判断当前选中的区域是不是纯文本，是纯文本动态添加一个父元素div
    createDiv(commonAncestorContainer)
    // 设置对应的样式
    if (ev == 'lineHeight') {
      commonAncestorContainer.parentElement.style.lineHeight = value
    }
    if (ev == 'textIndent') {
      commonAncestorContainer.parentElement.style.textIndent = value
    }
  } else {
    // 循环找出选择区域的元素开始的位置和结束的位置
    for (let i: number = 0; i < childArr.length; i++) {
      // 记录选中区域的开始元素位置
      if ((startIndex == 0 && childArr[i].innerText == startContainer) || childArr[i].textContent == startContainer) {
        startIndex = i
      }
      // 记录选中区域的结束元素位置
      if ((endIndex == 0 && childArr[i].innerText == endContainer) || childArr[i].textContent == endContainer) {
        endIndex = i
      }
    }
    // 循环找出选择区域的元素， 并从开始位置设置行高到结束位置
    for (let i: number = 0; i < childArr.length; i++) {
      // 设置对应的样式
      if (ev == 'lineHeight') {
        if (i >= startIndex && i <= endIndex && !!childArr[i].style) {
          childArr[i].style.lineHeight = value
        }
      }
      if (ev == 'textIndent') {
        if (i == startIndex) {
          if (!!childArr[i].style) {
            childArr[i].style.textIndent = value
          } else {
            createDiv(commonAncestorContainer)
            childArr[i].parentElement.style.textIndent = value
          }
        }
      }
    }
  }
}

// 清楚选区所有元素的样式
const clearStyle = (): void => {
  let { childArr } = getRangeHtml()
  if (!!childArr.length) {
    // 循环找出选择区域的元素， 并从开始位置设置行高到结束位置
    for (let i: number = 0; i < childArr.length; i++) {
      if (!!childArr[i].style) {
        childArr[i].style = ''
        childArr[i].removeAttribute('style')
      }
    }
  }
}

// 富文本进行编辑
export const useEdit = (ev: string, val: string): void => {
  console.log(ev, val)

  // 解构 store的配置数据, 获取光标保留的位置或选定对象
  const pageConfigStore: IPageConfigStore = usePageConfigStore()
  const { lastAangeAt } = toRefs<any>(pageConfigStore)
  let lastAange: any = lastAangeAt.value

  // 如果未选择编辑内容或光标，直接返回，并给与提示
  if (lastAange == null) {
    ElMessage({
      showClose: true,
      message: '未选择编辑操作的内容!',
      type: 'error',
    })
    return
  }

  // 判断是否存在编辑的属性类型
  if (!ev) return

  // 获取光标
  let selection: any = window.getSelection && window.getSelection()
  // 清除所有选区
  selection.removeAllRanges()
  // 添加最后光标还原之前的状态
  selection.addRange(lastAange)
  // 获取光标对象
  let range: any = selection.getRangeAt(0)

  // 获取富文本操作的需要操作的属性类型
  let cmd_val: any = ev.split(':')

  // 根据操作类型设置进行富文本的内容编辑
  if (cmd_val[0] == 'copy') {
    // 复制选中的文本
    document.execCommand(cmd_val[0])
  } else if (cmd_val[0] == 'lineHeight') {
    // 设置行间距
    setStyle(cmd_val[0], !!cmd_val[1] ? cmd_val[1] : '')
  } else if (cmd_val[0] == 'foreColor' || cmd_val[0] == 'backColor') {
    // 设置字体颜色和字体背景颜色
    document.execCommand(cmd_val[0], false, val)
  } else if (cmd_val[0] == 'clear') {
    // 清空所有内容
    // ;(document.querySelector('#emr_page_editArea') as Element).innerHTML = ''
    let editArea: any = document.querySelectorAll('.emr_page_editArea')
    for (let item of editArea) {
      item.innerHTML = ''
    }
  } else {
    if (cmd_val[0] == 'removeFormat') {
      // 清楚格式特殊处理
      clearStyle()
    }
    if (cmd_val[0] == 'textIndent' || cmd_val[0] == 'cancelTextIndent') {
      // 设置或取消首行缩进特殊处理
      setStyle('textIndent', cmd_val[0] == 'textIndent' ? '2em' : '0')
    }
    document.execCommand(cmd_val[0], false, !!cmd_val[1] ? cmd_val[1] : null)
  }

  // 克隆一个光标
  range = range.cloneRange()
  // 光标开始和光标结束重叠
  range.collapse(true)
  // 插入新的光标对象
  selection?.addRange(range)
  // 记录最后光标对象
  pageConfigStore.$patch?.((state: IPageConfigStore) => {
    state.lastAangeAt = selection.getRangeAt(0)
  })
}
